using LightCAD.MathLib;
using System;
using System.Collections;
using System.Collections.Generic;

using static LightCAD.MathLib.MathEx;

namespace LightCAD.Three
{
    public class MeshPhysicalMaterial : MeshStandardMaterial
    {
        #region Properties

        //public Texture clearcoatMap;
        //public Texture clearcoatNormalMap;
        //public Texture clearcoatRoughnessMap;
        //public double clearcoatRoughness;
        //public Vector2 clearcoatNormalScale;
        //public JsArr<double> iridescenceThicknessRange;
        //public Color sheenColor;
        //public Texture sheenColorMap;
        //public Texture sheenRoughnessMap;
        //public double sheenRoughness;
        //public double thickness;
        //public double attenuationDistance;
        //public Color attenuationColor;
        //public double specularIntensity;
        //public Color specularColor;
        //public double sheen;
        //public double clearcoat;
        //public double iridescence;
        //public double transmission;
        //public double ior;
        //public double iridescenceIOR;
        //public Texture iridescenceMap;
        //public Texture iridescenceThicknessMap;

        //public Texture transmissionMap;
        //public Texture thicknessMap;
        //public Texture specularIntensityMap;
        //public Texture specularColorMap;
        #endregion

        #region constructor
        public MeshPhysicalMaterial() 
        {
            this.defines = new JsObj<object>{
                    {"STANDARD", "" },{"PHYSICAL", ""}
                };
            this.type = "MeshPhysicalMaterial";
            this.clearcoatMap = null;
            this.clearcoatRoughness = 0.0;
            this.clearcoatRoughnessMap = null;
            this.clearcoatNormalScale = new Vector2(1, 1);
            this.clearcoatNormalMap = null;
            this.ior = 1.5;
            this.iridescenceMap = null;
            this.iridescenceIOR = 1.3;
            this.iridescenceThicknessRange = new ListEx<double> { 100, 400 };
            this.iridescenceThicknessMap = null;
            this.sheenColor = new Color(0x000000);
            this.sheenColorMap = null;
            this.sheenRoughness = 1.0;
            this.sheenRoughnessMap = null;
            this.transmissionMap = null;
            this.thickness = 0;
            this.thicknessMap = null;
            this.attenuationDistance = Infinity;
            this.attenuationColor = new Color(1, 1, 1);
            this.specularIntensity = 1.0;
            this.specularIntensityMap = null;
            this.specularColor = new Color(1, 1, 1);
            this.specularColorMap = null;
            this.sheen = 0.0;
            this.clearcoat = 0;
            this.iridescence = 0;
            this.transmission = 0;
        }
       
        #endregion

        #region properties
        public MeshPhysicalMaterial setSheen(double value)
        {
            if (this.sheen > 0 != value > 0)
            {
                this.version++;
            }
            this.sheen = value;
            return this;
        }

        public MeshPhysicalMaterial setClearcoat(double value)
        {
            if (this.clearcoat > 0 != value > 0)
            {
                this.version++;
            }
            this.clearcoat = value;
            return this;
        }

        public MeshPhysicalMaterial setIridescence(double value)
        {
            if (this.iridescence > 0 != value > 0)
            {
                this.version++;
            }
            this.iridescence = value;
            return this;
        }
        public MeshPhysicalMaterial setTransmission(double value)
        {
            if (this.transmission > 0 != value > 0)
            {
                this.version++;
            }
            this.transmission = value;
            return this;
        }
        public double getReflectivity()
        {
            return (MathEx.Clamp(2.5 * (this.ior - 1) / (this.ior + 1), 0, 1));
        }
        public MeshPhysicalMaterial setReflectivity(double value)
        {
            this.ior = (1 + 0.4 * reflectivity) / (1 - 0.4 * reflectivity);
            return this;
        }
        #endregion

        #region methods
        public MeshPhysicalMaterial copy(MeshPhysicalMaterial source)
        {
            base.copy(source);
            this.defines = new JsObj<object>
                {
                    { "STANDARD", ""},
                    { "PHYSICAL", "" }
                };
            this.clearcoat = source.clearcoat;
            this.clearcoatMap = source.clearcoatMap;
            this.clearcoatRoughness = source.clearcoatRoughness;
            this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
            this.clearcoatNormalMap = source.clearcoatNormalMap;
            this.clearcoatNormalScale.Copy(source.clearcoatNormalScale);
            this.ior = source.ior;
            this.iridescence = source.iridescence;
            this.iridescenceMap = source.iridescenceMap;
            this.iridescenceIOR = source.iridescenceIOR;
            this.iridescenceThicknessRange = source.iridescenceThicknessRange.ToListEx();
            this.iridescenceThicknessMap = source.iridescenceThicknessMap;
            this.sheen = source.sheen;
            this.sheenColor.Copy(source.sheenColor);
            this.sheenColorMap = source.sheenColorMap;
            this.sheenRoughness = source.sheenRoughness;
            this.sheenRoughnessMap = source.sheenRoughnessMap;
            this.transmission = source.transmission;
            this.transmissionMap = source.transmissionMap;
            this.thickness = source.thickness;
            this.thicknessMap = source.thicknessMap;
            this.attenuationDistance = source.attenuationDistance;
            this.attenuationColor.Copy(source.attenuationColor);
            this.specularIntensity = source.specularIntensity;
            this.specularIntensityMap = source.specularIntensityMap;
            this.specularColor.Copy(source.specularColor);
            this.specularColorMap = source.specularColorMap;
            return this;
        }
        public override Material clone()
        {
            return new MeshPhysicalMaterial().copy(this);
        }
        #endregion

    }
}
